use std::sync::Mutex;

use ipc_channel::platform::{self, OsIpcChannel, OsIpcReceiver, OsIpcSender};
use once_cell::sync::Lazy;

use super::R;

pub trait IpcExt {
    fn send_data<T: Into<Vec<u8>>>(&self, data: T) -> R;
    fn response<T: Into<Vec<u8>>>(&self, data: T) -> R;
    fn send_data_res<T: Into<Vec<u8>>>(&self, data: T) -> R<Vec<u8>>;
}

/// ipc管道缓存
static IPC_CHCHA: Lazy<Vec<Mutex<(OsIpcSender, OsIpcReceiver)>>> = Lazy::new(|| {
    let mut res = vec![];
    for _ in 0..4 {
        let (tx, rx) = platform::channel().unwrap();
        res.push(Mutex::new((tx, rx)));
    }
    res
});

impl IpcExt for OsIpcSender {
    fn send_data<T: Into<Vec<u8>>>(&self, data: T) -> R {
        self.send(&data.into(), vec![], vec![])
            .map_err(|e| format!("send_data error: {e:?}"))?;
        Ok(())
    }
    fn response<T: Into<Vec<u8>>>(&self, data: T) -> R {
        self.send_data(data)
    }
    fn send_data_res<T: Into<Vec<u8>>>(&self, data: T) -> R<Vec<u8>> {
        // for ele in IPC_CHCHA.iter() {
        //     let lock = match ele.try_lock() {
        //         Ok(v) => v,
        //         Err(_) => continue,
        //     };
        //     let tx = lock.0.clone();
        //     self.send(&data.into(), vec![OsIpcChannel::Sender(tx)], vec![])
        //         .map_err(|e| format!("{e:?}"))?;
        //     let (res, _, _) = lock.1.recv().map_err(|e| format!("{e:?}"))?;
        //     return Ok(res);
        // }

        let (tx, rx) = platform::channel()?;
        self.send(&data.into(), vec![OsIpcChannel::Sender(tx)], vec![])
            .map_err(|e| format!("{e:?}"))?;
        let (res, _, _) = rx.recv().map_err(|e| format!("{e:?}"))?;
        return Ok(res);
    }
}

pub trait LpcExt {
    fn recver<F: Fn(Vec<u8>, Option<OsIpcSender>) + Send + Clone + 'static>(&self, call: F);
    fn send<T: Into<Vec<u8>>>(&self, data: T) -> R;
    fn send_res<T: Into<Vec<u8>>>(&self, data: T) -> R<Vec<u8>>;
}

// pub trait LpcIndexExt {
//     fn send_index<T: Into<Vec<u8>>>(&self, data: T, index: usize, is_res: bool) -> R<Vec<u8>>;
//     fn send_all<T: Into<Vec<u8>> + Clone>(&self, data: T) -> R;
// }
